package main

import (
	"demo01/internal/conf"
	cfg "github.com/go-kratos/kratos/contrib/config/etcd/v2"
	kratoszap "github.com/go-kratos/kratos/contrib/log/zap/v2"
	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"
	clientv3 "go.etcd.io/etcd/client/v3"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	clientGrpc "google.golang.org/grpc"
	"os"
	"time"
)

// go build -ldflags "-X main.Version=x.y.z"
var (
	// Name is the name of the compiled software.
	Name string
	// Version is the version of the compiled software.
	Version string
	// flagconf is the config flag.
	//flagconf string

	id, _ = os.Hostname()
)

//func init() {
//	flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml")
//}

func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server) *kratos.App {
	return kratos.New(
		kratos.ID(id),
		kratos.Name(Name),
		kratos.Version(Version),
		kratos.Metadata(map[string]string{}),
		kratos.Logger(logger),
		kratos.Server(
			gs,
			hs,
		),
	)
}

func main() {
	//flag.Parse()

	// 首先，定义不同级别日志处理逻辑
	//highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
	//	return lvl >= zapcore.ErrorLevel
	//})
	//lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
	//	return lvl < zapcore.ErrorLevel
	//})

	// 输出到 ./test.json 文件
	f, err := os.OpenFile("loggers/test.json", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return
	}

	// 分别输出到文件和标准输出
	writeSyncer := zapcore.AddSync(f)
	writeSyncer2 := zapcore.AddSync(os.Stdout)

	encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
	encoder2 := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())

	//core := zapcore.NewTee(zapcore.NewCore(encoder, writeSyncer, highPriority), zapcore.NewCore(encoder2, writeSyncer2, lowPriority))
	core := zapcore.NewTee(zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel), zapcore.NewCore(encoder2, writeSyncer2, zapcore.DebugLevel))

	z := zap.New(core)
	//logger := log.With(log.NewStdLogger(os.Stdout),
	logger := log.With(kratoszap.NewLogger(z),
		"ts", log.DefaultTimestamp,
		"caller", log.DefaultCaller,
		"service.id", id,
		"service.name", Name,
		"service.version", Version,
		"trace.id", tracing.TraceID(),
		"span.id", tracing.SpanID(),
	)
	// create an etcd client
	client, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"10.10.22.104:12379"},
		DialTimeout: time.Second,
		DialOptions: []clientGrpc.DialOption{clientGrpc.WithBlock()},
	})
	if err != nil {
		log.Fatal(err)
	}

	// configure the source, "path" is required
	source, err := cfg.New(client, cfg.WithPath("/app-config.yaml"), cfg.WithPrefix(true))
	if err != nil {
		log.Fatal(err)
	}

	c := config.New(
		config.WithSource(
			source,
		),
	)
	defer c.Close()

	if err := c.Load(); err != nil {
		panic(err)
	}

	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}

	app, cleanup, err := wireApp(bc.Server, bc.Data, logger)
	if err != nil {
		panic(err)
	}
	defer cleanup()

	// start and wait for stop signal
	if err := app.Run(); err != nil {
		panic(err)
	}
}
